#!/usr/bin/env python
# -*- coding:utf-8 -*-
# author:ouyang time:2023/4/5



import json
import threading
import time
import socket
import base64
import os
import copy
import signal
from collections import deque


class TCPListen(threading.Thread):
    """
    传输连接车辆的信息
    """
    def __init__(self):

        threading.Thread.__init__(self)

        """ 定义常量 """
        self.run_environment = 'pc'

        """初始化TCP服务端"""
        self.tcp_server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        self.tcp_server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        self.server_port = 61121
        self.connect_obj_buff = deque()
        self.tcp_server.bind(('', self.server_port))

        """socket连接状态、数据缓存"""
        self.connect_sta = 0     # 连接状态变为断开状态
        self.thread_run = 0      # 线程结束状态

    def waite_for_connect(self):
        # 使socket处于监听状态，等待客户端的连接请求
        # 最多连接几个客户端
        self.tcp_server.listen(1)

        print("---------CAR Server start!---------")

        # 等待客户端连接连接，如果客户端连接，就会获取到客户端套接字连接和客户端地址
        conn, address = self.tcp_server.accept()
        print("Success connect from ", address)
        self.send_message(conn, "ok")  # 服务器连接需要得到密码确认
        data = conn.recv(4096)
        data = data.decode('utf-8')
        print(data)
        if data == 'ok':
            print("车辆连接成功！")
            return conn
        else:
            print("连接失败！")
            return 0

    def run(self):
            self.udp_server_task()

    def udp_server_task(self):

        while True:
            try:
                new_conn, address = self.waite_for_connect()
                if new_conn != 0:  # 如果都返回0,则表示建立连接异常
                    self.connect_obj_buff.append(new_conn)

            except Exception as e:
                print(e)
                return 0

    def get_conn_obj(self):
        """
        外部调用接口，返回收集的任务
        :return:
        """
        temp_task = []
        count = len(self.connect_obj_buff)
        if count != 0:
            for i in range(0, count):
                temp_task.append(self.connect_obj_buff.popleft())
            print(temp_task)
            return temp_task
        else:
            return None

    def send_message(self, connect, data):
        """
        当多个线程需要发送消息时，要上锁
        多线程是指， 一个线程发送头信息， 另一个线程发送任务信息
        :param data:
        :param connect:
        :return:
        """
        pre_send = json.dumps(data)
        connect.send(pre_send.encode('utf-8'))
        time.sleep(0.001)  # 延时为经验值


class UDPListen(threading.Thread):
    """
    收集车辆的信息
    """
    def __init__(self):

        threading.Thread.__init__(self)

        """ 定义常量 """
        self.run_environment = 'pc'

        """初始化UDP服务端"""
        self.udp_server = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        self.udp_server.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
        self.server_port = 1060
        self.connect_obj_buff = deque()  # UDP接收数据缓存区

        """socket连接状态、数据缓存"""
        self.connect_sta = 0     # 连接状态变为断开状态
        self.thread_run = 0      # 线程结束状态

    def waite_for_connect(self):
        # 使socket处于监听状态，等待客户端的连接请求
        # 最多连接几个客户端
        data, address = self.udp_server.recvfrom(65535)
        if data:
            json_buff = data.decode('utf-8')
            buff = json.loads(json_buff)
            self.connect_obj_buff.append(buff)

    def run(self):
            self.udp_server_task()

    def udp_server_task(self):
        self.udp_server.bind(('', self.server_port))
        while True:
            try:
                self.waite_for_connect()
                time.sleep(1)

            except Exception as e:
                print(e)
                return 0

    def get_broadcast_info(self):
        """
        外部调用接口，返回收集的RSU信息
        :return:
        """
        temp_task = []
        count = len(self.connect_obj_buff)
        if count != 0:
            for i in range(0, count):
                temp_task.append(self.connect_obj_buff.popleft())
            return temp_task
        else:
            return None


if __name__ == '__main__':
    car = TCPListen()
    car.run()
